package base.items;

import static util.Constant.STR_INVALID_ID;

import java.io.File;
import java.util.HashSet;

import lib.TagManager;

import util.FileOperator;

import base.Comment;
import base.Tag;

public abstract class Item {
	private Integer ID;
	private String type;
	private String title;
	private HashSet<Integer> tags;
	private HashSet<Integer> comments;
	private String path;

	/**
	 * Constructor of the {@code class}. Create an item from parameter.
	 * 
	 * @param ID
	 *            the item ID.
	 * 
	 * @throws IllegalArgumentException
	 */
	public Item(Integer ID) throws IllegalArgumentException {
		if (ID < 0)
			throw new IllegalArgumentException(STR_INVALID_ID);

		this.ID = ID;
		this.tags = new HashSet<Integer>();
		this.comments = new HashSet<Integer>();
	}

	/**
	 * Constructor of the {@code class}. Create an item from parameter.
	 * 
	 * @param ID
	 *            the item ID.
	 * 
	 * @param type
	 *            the item type.
	 * 
	 * @param title
	 *            the item title.
	 * 
	 * @param tags
	 *            the item tags list.
	 * 
	 * @throws IllegalArgumentException
	 */
	public Item(Integer ID, String type, String title, HashSet<Integer> tags,
			HashSet<Integer> comments) throws IllegalArgumentException {
		if (ID < 0)
			throw new IllegalArgumentException(STR_INVALID_ID);

		this.ID = ID;
		this.type = type;
		this.title = title;
		this.tags = tags;
		this.comments = comments;
	}

	/**
	 * @return the ID
	 */
	public Integer getID() {
		return ID;
	}

	/**
	 * @param ID
	 *            the ID to set
	 */
	public void setID(Integer ID) {
		this.ID = ID;
	}

	/**
	 * @return the type
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * @param title
	 *            the title to set
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * @return the title
	 */
	public String getPath() {
		return path;
	}

	/**
	 * @param path
	 *            the path to set
	 */
	public void setPath(String path) {
		File file = new File(path);
		if (file.isFile() && file.canRead()) {
			this.path = path;
			parseData();
		}
	}

	/**
	 * @return the tags
	 */
	public HashSet<Integer> getTags() {
		return tags;
	}

	/**
	 * @param tags
	 *            the tags to set
	 */
	public void setTags(HashSet<Integer> tags) {
		this.tags = tags;
	}

	/**
	 * @return the comments
	 */
	public HashSet<Integer> getComments() {
		return comments;
	}

	/**
	 * @param comments
	 *            the comments to set
	 */
	public void setComments(HashSet<Integer> comments) {
		this.comments = comments;
	}

	/**
	 * @param tagid
	 *            the tag ID to add
	 * 
	 */
	public boolean addTag(Integer tagid) {
		return this.tags.add(tagid);
	}

	/**
	 * @param tag
	 *            the tag to add
	 * 
	 */
	public boolean addTag(Tag tag) {
		return this.addTag(tag.getID());
	}

	/**
	 * @param tag
	 *            the tag to remove
	 * 
	 */
	public boolean removeTag(Tag tag) {
		return this.removeTag(tag.getID());
	}

	/**
	 * @param tagID
	 *            the tag to remove
	 * 
	 */
	public boolean removeTag(Integer tagID) {
		return this.tags.remove(tagID);
	}

	/**
	 * @param commentid
	 *            the comment ID to add
	 * 
	 */
	public boolean addComment(Integer commentid) {
		return this.comments.add(commentid);
	}

	/**
	 * @param comment
	 *            the comment to add
	 * 
	 */
	public boolean addComment(Comment comment) {
		return this.addComment(comment.getID());
	}

	/**
	 * @param tag
	 *            the comment to remove
	 * 
	 */
	public boolean removeComment(Comment tag) {
		return this.removeComment(tag.getID());
	}

	/**
	 * @param commentID
	 *            the commentID to remove
	 * 
	 */
	public boolean removeComment(Integer commentID) {
		return this.comments.remove(commentID);
	}

	/**
	 * Returns a {@code String} object representing the Item's value.
	 * 
	 * @return a string representation of the item.
	 */
	@Override
	public String toString() {
		String res = "";
		res += "Item ID: " + ID + "\nType: " + type + "\nTitle: " + title;
		if (!tags.isEmpty()) {
			res += "\nList of tags :\n";
			TagManager tagManager = TagManager.getInstance();

			for (Integer ID : tags) {
				res += "    * " + tagManager.get(ID).toString() + "\n";
			}
		}
		return res;
	}

	/**
	 * Check equality between two Items. If this method get an Event, it
	 * compares the two IDs, else it returns false.
	 * 
	 * @param other
	 *            Another object
	 * 
	 * @return {@code true} if the parameter is an event; {@code false}
	 *         otherwise.
	 */
	public boolean equals(Object other) {
		return (other instanceof Item && ((Item) other).getID() == this.ID);
	}

	/**
	 * 
	 * @return <code>true</code> si le fichier est bien défini et du bon type,
	 *         <code>false</code> sinon.
	 */
	public boolean parseData() {
		if (path == null)
			return false;
		
		boolean trouve = false;
		for (String s : allowedMimeTypes()) {
			if (s.equals(FileOperator.getMimeType(path)))
				trouve = true;
		}
		if (!trouve)
			path = null;
		return trouve;
	}

	public abstract String[] allowedMimeTypes();

}
